'use client'
import React, { FC, useContext, useEffect, useMemo, useRef, useState } from 'react'
import { useRouter } from 'next/navigation'
import { Form, Input, Select, Table, Radio, Segmented } from 'antd'
import { ArrowLeftOutlined } from '@ant-design/icons'
import { getSearchParams } from './paramsUtils'
import { getQueryParams } from '@/utils/getUrlParams'
import { createCustomCollection, fetchCustomCollection, updateCustomCollection } from '@/service/tools'
import { publishName } from '@/service/apps'
import Button from '@/app/components/base/button'
import Toast from '@/app/components/base/toast'
import ReleaseModal from '../../apps/component/base/releaseModal'
import ConfigVar from '@/app/components/tools/create-var'
import s from '../tool.module.css'
const CreateByUrl: FC = () => {
  const router = useRouter()
  const tenant_id = getQueryParams('tenant_id') || ''
  const [release, setRelease] = useState(false)
  const [method, setMethod] = useState('POST')
  const [url, setUrl] = useState('')
  const [appId, setAppId] = useState('')
  const [data, setData] = useState<any>([])
  const [value, setValue] = useState(1)
  const [listData, setListName] = useState([])
  const publicName = async () => {
    const res = await publishName()
    setListName(res)
    setRelease(true)
  }

  useEffect(() => {
    (
      async () => {
        console.log(getQueryParams('app_id'), "getQueryParams('app_id')")
        if (getQueryParams('app_id')) {
          setAppId(getQueryParams('app_id'))
        }
      }
    )()
  }, [])

  const [showType, setShowType] = useState('dcoos');
  const [headerVariables, setHeaderVariables] = useState<any>([
    {
      key: 'X-APP-ID',
      max_length: 48,
      required: true,
      type: 'string',
      value: ''
    },
    {
      key: 'X-APP-KEY',
      max_length: 48,
      required: true,
      type: 'string',
      value: ''
    }
  ])
  const [newParamsVariables, setNewParamsVariables] = useState<any>([]);
  const [paramsVariables, setParamsVariables] = useState<any>([
    {
      key: 'systemName',
      max_length: 48,
      required: true,
      type: 'string',
      value: '',
      desc: '',
      getType: 'Header'
    },
    {
      key: 'API',
      max_length: 48,
      required: true,
      type: 'string',
      value: '',
      desc: '',
      getType: 'Header'
    },
    {
      key: 'userId',
      max_length: 48,
      required: false,
      type: 'string',
      value: '',
      desc: '',
      getType: 'Header'
    },
    {
      key: 'session_id',
      max_length: 48,
      required: false,
      type: 'string',
      value: '',
      desc: '',
      getType: 'Header'
    },
    {
      key: 'areaCode',
      max_length: 48,
      required: false,
      type: 'string',
      value: '',
      desc: '',
      getType: 'Header'
    },
    {
      key: 'srvCode',
      max_length: 48,
      required: false,
      type: 'string',
      value: '',
      desc: '',
      getType: 'Header'
    },
    {
      key: 'apiData',
      max_length: 48,
      required: true,
      type: 'object',
      value: '',
      desc: '',
      getType: 'Header'
    }
  ])
  const [totalParams, setTotalParams] = useState<any>({
    provider: '',
    credentials: {},
    icon: {
      content: '',
      background: '',
    },
    schema_type: 'openapi',
    schema: {
      openapi: '3.1.0',
      info: {
        title: '',
        description: '',
        version: 'v1.0.0',
      },
      servers: [
        {
          url: '',
        },
      ],
      paths: {
      },
      components: {
        schemas: {},
      },
    },
    labels: [],
  })
  const searchObj = {
    original_provider: getSearchParams('original_provider'),
    provider: getSearchParams('provider'),
    desc: getSearchParams('desc'),
  }
  const getRoute = (url: string): string => {
    if (!url.includes('/')) {
      if (url.length > 10) {
        return url.slice(-10)
      } else {
        return url
      }
    }
    const match = url.match(/^[a-zA-Z]+:\/\/[^/]+|^[^/]+/); // 匹配协议和域名部分
    const path = match ? url.slice(match[0].length) : '/'; // 提取路径部分
    const newPath = path.split('?')[0] || '/'
    if (newPath.length > 10) {
      return newPath.slice(-10)
    } else {
      return newPath
    }
  };

  const pathRoute = (url: string) => {
    if (!url.includes('/')) {
      return url
    }
    const match = url.match(/^[a-zA-Z]+:\/\/[^/]+|^[^/]+/); // 匹配协议和域名部分
    const path = match ? url.slice(match[0].length) : '/'; // 提取路径部分
    const newPath = path.split('?')[0] || '/'
    return newPath
  }
  useEffect(() => {
    if (typeof window !== 'undefined')
      document.title = '通过URL接入插件'
    const newTotalParams = { ...totalParams }
    if (searchObj.original_provider) {
      fetchCustomCollection(searchObj.original_provider, tenant_id).then((res: any) => {
        res.schema = JSON.parse(res.schema)
        res.provider = searchObj.original_provider
        res.original_provider = searchObj.original_provider
        setValue(res?.access_type || 1)
        const inputUrl = res.schema.servers[0].url;
        setTotalParams(res)
        setUrl(inputUrl)
        const methodObj: any = Object.values(res.schema.paths)[0]
        const newMethod = Object.keys(methodObj)[0];

        const params: any = [];
        const parameters = Object.values(methodObj)[0]?.parameters;
        (parameters || []).map((param: any) => {
          params.push({ ...param, key: param.name, type: param?.schema?.type, value: param?.schema?.default });
        });


        setMethod(newMethod)
        const newHeaders = [...headerVariables]
        const tempHeaders = []
        for (const i in res.credentials) {
          if (i !== 'auth_type') {
            let found = false
            // 这个for循环是为了将返回的headers和已有的headers进行合并，避免重复添加
            for (let j = 0; j < newHeaders.length; j++) {
              if (newHeaders[j].key === i) {
                newHeaders[j].value = res.credentials[i]
                found = true
                break
              }
            }
            if (!found) {
              tempHeaders.push({
                key: i,
                value: res.credentials[i],
                max_length: 48,
                required: true,
                type: 'string',
              })
            }
          }
        }

        newHeaders.push(...tempHeaders)
        setHeaderVariables(newHeaders)
        let newParams: any = [...paramsVariables]
        let newObj: any = methodObj[newMethod].parameters.filter((item: any) => item.name !== 'apiData').map((item: any) => {
          return {
            key: item.name,
            type: item.schema.type,
            required: item.required,
            max_length: 48,
            value: item.schema.default || '',
          }
        })
        let newArr: any = []
        if (methodObj[newMethod].parameters.some((item: any) => item.name === 'apiData')) {
          const apiDataItem = methodObj[newMethod].parameters.find((item: any) => item.name === 'apiData')
          let keys = Object.keys(apiDataItem.schema.properties)
          keys.forEach((v: any, i: any) => {
            newArr.push({
              key: v,
              type: apiDataItem.schema.properties[v].type,
              required: apiDataItem.schema.required[i] === keys[i] ? true : false,
              max_length: 48,
              value: apiDataItem.schema.properties[v].default,
            })
          })
        }

        const combined = [...newObj, ...newParams, ...newArr].reduce((acc, current) => {
          const existing = acc.find((item: any) => item.key === current.key)
          if (existing) {
            return acc
          } else {
            return [...acc, current]
          }
        }, [])
        if (params && params[0] && params[0].showType === 'unDcoos') {
          setNewParamsVariables(params)
          setShowType('unDcoos')
        } else {
          setParamsVariables(combined)
        }
        setData([{
          name: searchObj.original_provider,
          desc: methodObj[method].description,
          method,
          path: getRoute(inputUrl),
        }])
      })
    }
    else {
      newTotalParams.provider = searchObj.provider
      setTotalParams(newTotalParams)
    }
  }, [])

  const handleHeaderVariablesChange = (vals: any) => {
    setHeaderVariables(vals)
  }

  const handleParamsVariablesChange = (vals: any) => {
    setParamsVariables(vals)
  }

  const handleNewParamsVariables = (vals: any) => {
    setNewParamsVariables(vals)
  }

  const getParams = () => {
    const newTotalParams = { ...totalParams }
    if (showType === 'dcoos' && headerVariables.length) {
      newTotalParams.credentials = {
        auth_type: 'none',
      }
      headerVariables.forEach((item: any) => {
        newTotalParams.credentials[item.key] = item.value
      })
    }
    else {
      newTotalParams.credentials = { auth_type: 'none' }
    }
    if (tenant_id !== '') {
      newTotalParams.tenant_id = tenant_id
    }
    newTotalParams.provider = getQueryParams('original_provider') ?? getQueryParams('provider')
    newTotalParams.schema.servers = [{ url: url.split('?')[0] }]

    const parameters = (showType === 'dcoos' ? paramsVariables : newParamsVariables).map((item: any) => {
      return {
        name: item.key,
        in: 'query',
        description: item.desc || '',
        required: item.required,
        desc: item.desc || '', //undcoos 描述信息
        showType: showType,
        getType: showType === 'unDcoos' ? item.getType || 'Header' : '',
        schema: {
          type: item.type,
          default: item.value,
        },
      }
    })

    newTotalParams.schema.paths = {
      [getRoute(url)]: {
        [method]: {
          operationId: searchObj.provider ? searchObj.provider || '' : data[0]?.name || '',
          description: searchObj.provider ? '' : data[0]?.desc || '',
          deprecated: false,//
          parameters: parameters,
        },
      },
    }
    newTotalParams.schema = JSON.stringify(newTotalParams.schema)
    newTotalParams.access_type = value === 1 ? 1 : 2
    return newTotalParams
  }
  const jumpToTest = () => {
    let data: any, dataAnother: any
    let schemaString: string
    if (showType === 'unDcoos') {
      dataAnother = {
        url: url,
        methods: method,
        headers: {},
        body: {},
        query: {}
      }
      newParamsVariables.map(record => {
        if (record.key) {
          if (record.getType === 'body') {
            dataAnother.body[record.key] = record.value;
          } else if (record.getType === 'Query') {
            dataAnother.query[record.key] = record.value;
          } else {
            dataAnother.headers[record.key] = record.value;
          }
        }
      })
    }
    if (searchObj.original_provider) {
      data = {
        ...getParams(),
        schema: {},
      }
      schemaString = transformOpenApiToObj(getParams().schema)
    } else {
      data = {
        ...getParams(),
        schema: {},
      }
      schemaString = transformOpenApiToObj(getParams().schema)
    }
    const dataString = encodeURIComponent(JSON.stringify(data))
    const dataAnotherString = encodeURIComponent(JSON.stringify(dataAnother))
    const urls = `/tools/createByCode?method=${method}&url=${getRoute(url)}&showType=${showType}&schema=${JSON.stringify(schemaString)}&dataAnother=${dataAnotherString}&data=${dataString}&name=${getQueryParams('original_provider') || getQueryParams('provider')}&value=${value}`
    router.push(urls)
  }

  const back = () => {
    router.push('/apps?category=area')
  };

  const validateParams = (params: any[]): boolean => {
    for (let param of params) {
      if (param.type === "number") {
        if (!/^\d+$/.test(param.value)) {
          return false
        }
      }
    }
    return true
  }

  const transformOpenApiToObj = (jsons: any) => {
    let json = JSON.parse(jsons)
    // 预留需要保留在根的字段名
    const rootNames = value === 1 ? ["systemName", "API", "userId", "session_id", "areaCode", "srvCode", "apiData"] : ["systemName", "API", "apiData"]
    // 初始化 apiData 下的 schema 属性结构
    const apiDataSchema: any = {
      type: "object",
      properties: {},
      required: []
    }
    json.paths[getRoute(url)][method].parameters = json.paths[getRoute(url)][method].parameters.reduce((acc: any, param: any) => {
      if (rootNames.includes(param.name) || showType === 'unDcoos') {
        // 保留指定字段在根
        acc.push(param)
      } else {
        // 其余字段放入 apiData 的 schema 属性中的 properties
        apiDataSchema.properties[param.name] = {
          type: param.schema.type,
          default: param.schema.default
        }
        // 若 required 为 true 则放入 required 数组
        if (param.required) {
          apiDataSchema.required.push(param.name)
        }
      }
      return acc
    }, [])
    // 将 apiData 的 schema 赋值
    const apiDataParam = json.paths[getRoute(url)][method].parameters.find((param: any) => param.name === "apiData")
    if (apiDataParam && apiDataParam.schema) {
      apiDataParam.schema = apiDataSchema;
    }

    return json
  }

  const save = () => {
    if (validateParams(paramsVariables)) {
      if (url === '') {
        Toast.notify({
          type: 'error',
          message: '请先输入url',
        })
        return
      }
      setData([
        {
          name: searchObj.provider || searchObj.original_provider,
          desc: '',
          method,
          path: pathRoute(url),
        },
      ])

      let params: any = getParams()
      let json = transformOpenApiToObj(params.schema)
      params.schema = JSON.stringify(json)
      const handleResponse = (res: any) => {
        Toast.notify({
          type: 'success',
          message: '保存成功',
        })
        setAppId(res.provider_id || '')
      }

      const handleError = (err: any) => {
        Toast.notify({
          type: 'error',
          message: '保存失败',
        })
      }

      let promise: Promise<any>
      if (params.original_provider || appId !== '') {
        promise = updateCustomCollection(params)
      } else {
        promise = createCustomCollection(params)
      }

      promise
        .then(handleResponse)
        .catch(handleError)

      // back()
    } else {
      Toast.notify({
        type: 'error',
        message: '参数格式错误,请重新填写',
      })
    }
  }
  const EditableContext: any = React.createContext(null)
  const EditableRow = ({ index, ...props }: any) => {
    const [form] = Form.useForm()
    return (
      <Form form={form} component={false}>
        <EditableContext.Provider value={form}>
          <tr {...props} />
        </EditableContext.Provider>
      </Form>
    )
  }

  const EditableCell = ({
    title,
    editable,
    children,
    dataIndex,
    record,
    handleSave,
    ...restProps
  }: any) => {
    const [editing, setEditing] = useState(false)//
    const inputRef: any = useRef(null)
    const form: any = useContext(EditableContext)
    useEffect(() => {
      if (editing)
        inputRef.current?.focus()
    }, [editing])
    const toggleEdit = () => {
      setEditing(!editing)
      form.setFieldsValue({
        [dataIndex]: record[dataIndex],
      })
    }
    const saved = async () => {
      try {
        const values = await form.validateFields()
        toggleEdit()
        handleSave({
          ...record,
          ...values,
        })
      }
      catch (e) {
        Toast.notify({
          type: 'error',
          message: '参数格式错误,请重新填写',
        })
      }
    }
    let childNode = children
    if (editable) {
      childNode = editing
        ? (
          <Form.Item
            style={{
              margin: 0,
            }}
            name={dataIndex}
          >
            <Input ref={inputRef} onPressEnter={saved} onBlur={saved} />
          </Form.Item>
        )
        : (
          <div
            className={s.editableWrap}
            style={{
              height: 30,
              paddingInlineEnd: 24,
            }}
            onClick={toggleEdit}
          >
            {children}
          </div>
        )
    }
    return <td {...restProps}>{childNode}</td>
  }

  const handleSave = (row: any) => {
    const newData = [...data]
    const index = newData.findIndex(item => row.key === item.key)
    const item = newData[index]
    newData.splice(index, 1, {
      ...item,
      ...row,
    })
    setData(newData)
    const newSchema: any = { ...totalParams }
    newSchema.schema.paths[getRoute(url)][method].description = row.desc
    setTotalParams(newSchema)
  }

  const components = {
    body: {
      row: EditableRow,
      cell: EditableCell,
    },
  }

  const defaultColumns = [
    {
      title: '名称',
      dataIndex: 'name',
      key: 'name',
    },
    {
      title: '描述',
      dataIndex: 'desc',
      key: 'desc',
      editable: true,
    },
    {
      title: '方法',
      dataIndex: 'method',
      key: 'method',
    },
    {
      title: '路径',
      dataIndex: 'path',
      key: 'path',
    },
    {
      title: '操作',
      dataIndex: 'action',
      key: 'action',
      render: (_: any) => (
        <Button className={s.save} onClick={jumpToTest} >测试</Button>
      ),
    },
  ]

  const columns = defaultColumns.map((col) => {
    if (!col.editable)
      return col

    return {
      ...col,
      onCell: (record: any) => ({
        record,
        editable: col.editable,
        dataIndex: col.dataIndex,
        title: col.title,
        handleSave,
      }),
    }
  })

  const { Option } = Select
  const selectBefore = (
    <Select defaultValue="POST" onChange={setMethod} value={method}>
      <Option value="POST">POST</Option>
      <Option value="GET">GET</Option>
    </Select>
  )

  useMemo(() => {
    if (value === 1) {
      setParamsVariables([
        {
          key: 'systemName',
          max_length: 48,
          required: true,
          type: 'string',
          value: ''
        },
        {
          key: 'API',
          max_length: 48,
          required: true,
          type: 'string',
          value: ''
        },
        {
          key: 'userId',
          max_length: 48,
          required: false,
          type: 'string',
          value: ''
        },
        {
          key: 'session_id',
          max_length: 48,
          required: false,
          type: 'string',
          value: ''
        },
        {
          key: 'areaCode',
          max_length: 48,
          required: false,
          type: 'string',
          value: ''
        },
        {
          key: 'srvCode',
          max_length: 48,
          required: false,
          type: 'string',
          value: ''
        },
        {
          key: 'apiData',
          max_length: 48,
          required: true,
          type: 'object',
          value: ''
        }
      ])
      setHeaderVariables([{
        key: 'X-APP-ID',
        max_length: 48,
        required: true,
        type: 'string',
        value: ''
      },
      {
        key: 'X-APP-KEY',
        max_length: 48,
        required: true,
        type: 'string',
        value: ''
      }])
      setNewParamsVariables([])
    } else {
      setParamsVariables([
        // {
        //   key: 'systemName',
        //   max_length: 48,
        //   required: true,
        //   type: 'string',
        //   value: ''
        // },
        // {
        //   key: 'API',
        //   max_length: 48,
        //   required: true,
        //   type: 'string',
        //   value: ''
        // },
        // {
        //   key: 'apiData',
        //   max_length: 48,
        //   required: true,
        //   type: 'object',
        //   value: ''
        // }
      ])
      setHeaderVariables([])
      setNewParamsVariables([])
    }
  }, [value])

  return (
    <>
      <div className={s.create}>
        <div className={s.header}>
          <div className={s.back}>
            <div onClick={back} className={s.backIcon}><ArrowLeftOutlined />返回</div>
            <div style={{ fontWeight: 'bolder' }}>通过URL接入插件</div>
          </div>
          <div>
            <Segmented
              value={showType}
              options={[
                { label: '能力平台接入', value: 'dcoos' },
                { label: '其他平台接入', value: 'unDcoos' }
              ]}
              onChange={(value) => { setShowType(value); value === 'unDcoos' ? setValue(1) : '' }}
            />
          </div>
          <div>
            <Button className={s.save} onClick={save} >保存</Button>
            <Button variant="primary" onClick={() => publicName()}>发布</Button>
          </div>
        </div>
        <div className={s.wrapper}>
          <div className={s.body}>
            {
              showType === 'dcoos' && <div>
                <div>接入接口参数，填写每个请求和相应的参数</div>
                {/* <div style={{ display: 'flex', marginTop: '15px' }}>
                  <div>接入方式</div>
                  <div style={{ marginLeft: '10px' }}>
                    <Radio.Group defaultValue={1} value={value} onChange={(e: any) => { setValue(e.target.value) }}>
                      <Radio value={1}>能力平台接入</Radio>
                      <Radio value={2}>其他平台接入</Radio>
                    </Radio.Group>
                  </div>
                </div> */}
              </div>
            }
            <div className={s.urlWrapper}>
              <div style={{ width: '80px', textAlign: 'left' }}>url地址</div>
              <Input addonBefore={selectBefore} value={url} onChange={e => setUrl(e.target.value)} />
            </div>

            {
              showType === 'dcoos' && <div>
                <div>
                  <ConfigVar
                    btnTitle='增加header参数'
                    varTitle='请求头'
                    promptVariables={headerVariables}
                    onPromptVariablesChange={handleHeaderVariablesChange}
                  />
                </div>
                <div>
                  <ConfigVar
                    tableType="params"
                    btnTitle='增加参数'
                    varTitle='请求体'
                    promptVariables={paramsVariables}
                    onPromptVariablesChange={handleParamsVariablesChange}
                    radioValue={value}
                  />
                </div>
              </div>
            }
            {
              showType === 'unDcoos' && <div>
                <ConfigVar
                  tableType="paramsNew"
                  btnTitle='增加参数'
                  varTitle='配置输入参数'
                  promptVariables={newParamsVariables}
                  onPromptVariablesChange={handleNewParamsVariables}
                  radioValue={1}
                />
              </div>
            }
            <div style={{ marginTop: '20px' }}>
              <Table rowClassName={() => s.editableRow} components={components} columns={columns} dataSource={data} pagination={false} bordered />
            </div>
          </div>
        </div>
      </div>
      {
        release === true ? <ReleaseModal onClose={() => setRelease(false)} release={release} tabClick={'2'} appId={appId} listData={listData} ></ReleaseModal> : null
      }
    </>
  )
}
export default React.memo(CreateByUrl)
